package assignment;

import jade.content.ContentElement;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.basic.Action;
import jade.content.onto.basic.Result;
import jade.core.AID;
import jade.core.Agent;
import jade.core.Location;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.JADEAgentManagement.QueryPlatformLocationsAction;
import jade.domain.mobility.MobilityOntology;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import jade.proto.states.MsgReceiver;
import jade.wrapper.AgentContainer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

public class CuratorAgent extends Agent {
	private static ArrayList<Item> items = new ArrayList<Item>(600);
	private String filename = "data/ItemList.xls";
	transient private AgentContainer[] home = new AgentContainer[2];
	private Map<String, Location> locations = new HashMap<String, Location>();

	public void setup() {
		// Register the Curator service in the yellow pages
		DFAgentDescription dfd = new DFAgentDescription();
		dfd.setName(getAID());
		ServiceDescription sd = new ServiceDescription();
		sd.setType("Curator");
		sd.setName("Curator");
		dfd.addServices(sd);
		try {
			DFService.register(this, dfd);
		} catch (FIPAException fe) {
			fe.printStackTrace();
		}

		// Register language and ontology
		getContentManager().registerLanguage(new SLCodec());
		getContentManager().registerOntology(MobilityOntology.getInstance());

		// Create the container objects
		home[0] = Runtime.instance().createAgentContainer(new ProfileImpl());
		// home[1] = Runtime.instance().createAgentContainer(new ProfileImpl());

		getLocations();
		doMove(locations.get("Container-1"));

		Object[] args = getArguments();
		if (args != null)
			filename = args[0].toString();

		// get data from excel-file
		File inputWorkbook = new File(filename);
		Workbook w;
		try {
			w = Workbook.getWorkbook(inputWorkbook);
			// Get the first sheet
			Sheet sheet = w.getSheet(1);
			// Loop over first 10 column and lines
			Item item = null;
			for (int j = 0; j < sheet.getRows(); j++) {
				item = new Item();
				for (int i = 0; i < 10; i++) {
					Cell cell = sheet.getCell(i, j);
					if (i == 0)
						item.setId(cell.getContents());
					else if (i == 1)
						item.setTitle(cell.getContents());
					else if (i == 2)
						item.setSubject(cell.getContents());
					else if (i < 6)
						item.addType(cell.getContents());
					else if (i < 10)
						item.addMaterial(cell.getContents());
				}
				items.add(item);
			}
		} catch (BiffException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		this.addBehaviour(new MsgRecTour());
		this.addBehaviour(new MsgRecProfiler());

	}

	private class MsgRecProfiler extends MsgReceiver {

		public void action() {
			
			AID[] aid = new AID[1];
			aid[0] = getAID();
			MessageTemplate mt = MessageTemplate.and(
					MessageTemplate.MatchReceiver(aid),
					MessageTemplate.MatchPerformative(ACLMessage.INFORM));
			ACLMessage msg = myAgent.blockingReceive(mt);
			//System.out.println("profiler called curator"+msg);
			if (msg != null) {
				// System.out.println("Msg1 received");
				// Message received. Process it
				ArrayList<String> keywords = null;
				try {
					keywords = (ArrayList<String>) msg.getContentObject();
				
					
				} catch (UnreadableException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				
				ArrayList<Item> retItems = new ArrayList<Item>(600);
				for (int i = 1; i < items.size(); i++) {
					// to be changed
					for (int j = 0; j < keywords.size(); j++){
						if (items.get(i).getId().contains(keywords.get(j))){
							retItems.add(items.get(i));
						}
					}
				}
				// System.out.println(retItems[2]);
				// Return the ID of interesting objects so the user knows where
				// to go
				ACLMessage reply = msg.createReply();
				reply.setPerformative(ACLMessage.INFORM);

				try {
					reply.setContentObject(retItems);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				//System.out.println("Curator repling "+retItems);
				myAgent.send(reply);
			}

		}
	}

	private class MsgRecTour extends MsgReceiver {

		public void action() {

			AID[] aid = new AID[1];
			aid[0] = getAID();
			MessageTemplate mt = MessageTemplate.and(
					MessageTemplate.MatchReceiver(aid),
					MessageTemplate.MatchPerformative(ACLMessage.REQUEST));
			ACLMessage msg = myAgent.blockingReceive(mt);
			StringBuilder sb = new StringBuilder();

			if (msg != null) {
				// System.out.println("Msg1 received");
				// Message received. Process it
				ArrayList<String> keywords = new ArrayList<String>();
				ArrayList<String> temp =null;
				try {
					temp = (ArrayList<String>) msg.getContentObject();
					//remove duplicates
					for(String a:temp){
						if(!keywords.contains(a))
							keywords.add(a);
					}
					
					//some bug here 
					//System.out.println("Curator "+ keywords);
				} catch (UnreadableException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

				ArrayList<Item> retItems = new ArrayList<Item>(600);
				for (int i = 1; i < items.size(); i++) {
					for (int j = 0; j < keywords.size(); j++)
						if (items.get(i).getSubject().contains(keywords.get(j))){
							retItems.add(items.get(i));
							break;
						}
				}
				while(retItems.size()<25){
					retItems.add(items.get(new Random().nextInt(items.size())));
				}
				retItems.trimToSize();
				// System.out.println(retItems[2]);
				// Return the ID of interesting objects so the user knows where
				// to go
				ACLMessage reply = msg.createReply();
				reply.setPerformative(ACLMessage.PROPOSE);

				try {
					reply.setContentObject(retItems);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				myAgent.send(reply);
			}

		}
	}

	private void getLocations() {
		try {
			// Get available locations with AMS
			sendRequest(new Action(getAMS(), new QueryPlatformLocationsAction()));

			// Receive response from AMS
			MessageTemplate mt = MessageTemplate.and(
					MessageTemplate.MatchSender(getAMS()),
					MessageTemplate.MatchPerformative(ACLMessage.INFORM));
			ACLMessage resp = blockingReceive(mt);

			// Get locations from AMS from contentmanager
			ContentElement ce = getContentManager().extractContent(resp);
			Result result = (Result) ce;
			jade.util.leap.Iterator it = result.getItems().iterator();

			// add locationname to our hashmap
			while (it.hasNext()) {
				Location loc = (Location) it.next();
				locations.put(loc.getName(), loc);
				System.out.println(loc.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}



	void sendRequest(Action action) {
		// ---------------------------------
		getContentManager().registerLanguage(new SLCodec());
		getContentManager().registerOntology(MobilityOntology.getInstance());
		ACLMessage request = new ACLMessage(ACLMessage.REQUEST);
		request.setLanguage(new SLCodec().getName());
		request.setOntology(MobilityOntology.getInstance().getName());
		try {
			getContentManager().fillContent(request, action);
			request.addReceiver(action.getActor());
			send(request);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/*
	 * public static void main(String[] args){ CuratorAgent ca = new
	 * CuratorAgent(); ca.setup(); System.out.println(items); }
	 */
}
